﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Windows;
using HappyBa.Core;
using HappyBa.Core.Data;
using HappyBa.Core.Interfaces;
using HappyBa.Core.Reporting;
using HappyBa.Core.Validators;
using LightInject;
using Mnk.Library.Common.Log;
using Mnk.Library.WpfControls.Tools;
using HappyBa.Localization;
using ServiceStack.Text;

namespace HappyBa.Pages
{
    /// <summary>
    /// Interaction logic for ValidationPage.xaml
    /// </summary>
    public partial class ValidationPage
    {
        private readonly ILog log = LogManager.GetLogger<ValidationPage>();
        private IValidationFacade validationFacade;
        private IDataCache dataCache;
        private Config config;
        private readonly IServiceContainer container;
        private readonly IValidationReportGenerator reportGenerator;
        private IList<ValidationResult> lastResults;

        public ValidationPage()
        {
            InitializeComponent();
            container = ((MainWindow)Application.Current.MainWindow).Container;
            container.GetInstance<IDataCollector>().OnDataChanged += (o, e) => OnDataContextChanged(o, new DependencyPropertyChangedEventArgs());
            reportGenerator = container.GetInstance<IValidationReportGenerator>();
            DataContextChanged += OnDataContextChanged;
        }

        private void OnDataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
        {
            dataCache = container.GetInstance<IDataCache>();
            config = container.GetInstance<Config>();
            validationFacade = container.GetInstance<IValidationFacade>();
            lastResults = null;

            if(config.Current==null)return;

            try
            {
                var search = new MetricsSearch(config.Current.Search);
                var metrics = new Metrics(dataCache.Metrics.Data, search);
                var context = new ValidationContext
                {
                    Metrics = metrics,
                    ActiveEmployees = config.Current.ActiveEmployees.Select(x => x.Key).ToArray(),
                };
                lastResults = FilterWarnings(validationFacade.Validate(context)
                    .OrderBy(x => x.Type)
                    .ToArray());
                Results.Text = string.Join(Environment.NewLine, lastResults);
                Info.Text = string.Format("Erros: {0}, Warnings: {1}",
                    lastResults.Count(x => x.Type == ValidationResultType.Error),
                    lastResults.Count(x => x.Type == ValidationResultType.Warning)
                    );
            }
            catch (Exception ex)
            {
                log.Write(ex, "Can't validate data");
            }
        }

        private IList<ValidationResult> FilterWarnings(IList<ValidationResult> results)
        {
            const string extension = ".warn";
            const string dateFormat = "yyyy MMMM dd";
            var currentFile = DateTime.Now.ToString(dateFormat) + extension;
            var folder = Path.Combine(Folders.UserProfilesFolder, config.UserFolderName);
            var currentPath = Path.Combine(folder, currentFile);
            Directory.CreateDirectory(Path.GetDirectoryName(currentPath));
            if (File.Exists(currentPath)) File.Delete(currentPath);
            File.WriteAllText(currentPath, JsonSerializer.SerializeToString(results.Where(x=>x.Type==ValidationResultType.Warning)));
            if (!config.Current.Validation.HideOldWarnings) return results;
            var existFiles = new DirectoryInfo(folder).GetFiles("*" + extension).OrderBy(x => x.CreationTime).Where(x => !string.Equals(x.Name, currentFile)).ToArray();
            if (!existFiles.Any()) return results;
            var oldWarnings = JsonSerializer.DeserializeFromString<ValidationResult[]>(File.ReadAllText(existFiles.First().FullName));
            foreach (var file in existFiles.Skip(1))
            {
                file.Delete();
            }
            return
                results
                .Where(x => x.Type == ValidationResultType.Error ||
                        !oldWarnings.Any(w => string.Equals(x.Message, w.Message)))
                .ToArray();
        }

        private void ValidateClick(object sender, RoutedEventArgs e)
        {
            OnDataContextChanged(sender, new DependencyPropertyChangedEventArgs());
        }

        private void ExcelReportClick(object sender, RoutedEventArgs e)
        {
            try
            {
                if(lastResults==null)return;
                reportGenerator.Generate(lastResults);
            }
            catch (Exception ex)
            {
                log.Write(ex, "Can't generate report");
            }
        }
    }
}
